package com.lhkj.ct.wechat.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.lhkj.ct.base.constants.ConfigConstants;
import com.lhkj.ct.base.enums.IamsServiceEnum;
import com.lhkj.ct.base.enums.ReturnStatus;
import com.lhkj.ct.base.exception.BusinessException;
import com.lhkj.ct.base.model.ro.ActionResult;
import com.lhkj.ct.base.utils.ShiroUtil;
import com.lhkj.ct.base.utils.Validate;
import com.lhkj.ct.base.utils.http.HttpUtils;
import com.lhkj.ct.meta.admin.service.SysConfigService;
import com.lhkj.ct.meta.modules.auth.service.UserIdentityService;
import com.lhkj.ct.meta.modules.gauge.mapper.ScaleMapper;
import com.lhkj.ct.meta.modules.gauge.model.entity.TblScale;
import com.lhkj.ct.meta.modules.order.mapper.TblScaleOrderMapper;
import com.lhkj.ct.meta.modules.order.model.entity.TblScaleOrder;
import com.lhkj.ct.meta.modules.psychology.mapper.PsyRecordMapper;
import com.lhkj.ct.meta.modules.psychology.model.entity.TblScalePsyRecord;
import com.lhkj.ct.wechat.base.model.dto.WxJsapiOrderRequest;
import com.lhkj.ct.wechat.base.model.vo.JsapiResult;
import com.lhkj.ct.wechat.base.model.vo.WxPayOrderNotifyV3Result;
import com.lhkj.ct.wechat.service.WeChatPayService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 微信支付
 */
@Service
public class WeChatPayServiceImpl implements WeChatPayService {

    private static final Logger log = LoggerFactory.getLogger(WeChatPayServiceImpl.class);

    @Resource
    private TblScaleOrderMapper tblScaleOrderMapper;

    @Resource
    private PsyRecordMapper psyRecordMapper;

    @Resource
    private ScaleMapper scaleMapper;

    @Resource
    private SysConfigService sysConfigService;

    @Resource
    private UserIdentityService userIdentityService;

    @Override
    @Transactional
    public JsapiResult jsApiOrder(String scaleId) {
        TblScale scale = scaleMapper.selectById(scaleId);
        Validate.notNull(scale, "量表不存在或已被删除！");
//        TblUserIdentity userIdentity = userIdentityService.getByLoginUser(UserType.PLATFORM, IdentType.WXP);
//        Validate.notNull(userIdentity, "当前账户未绑定档案或绑定已失效，请重新绑定！");
        // 如无配置则使用默认配置
        String mchId = sysConfigService.selectConfigByKey(ConfigConstants.SYS_WECHAT_MCHID);
        String notifyUrl = sysConfigService.selectConfigByKey(ConfigConstants.SYS_WECHAT_PAY_NOTIFY_URL);
        int amount = scale.getAmount() == null ? 0 : scale.getAmount().multiply(new BigDecimal("100")).intValue();
        if (amount == 0) {
            log.info("免费量表 => id:{}, 名称:{}",scaleId, scale.getDisplayName());
            TblScalePsyRecord build = TblScalePsyRecord.builder()
                    .patId(ShiroUtil.getAuthUserInfo().getUserId())
                    .scaleId(scaleId)
                    .psyType(1)
                    .createTime(LocalDateTime.now())
                    .build();
            psyRecordMapper.insert(build);
            JsapiResult jsapiResult = new JsapiResult();
            jsapiResult.setFree(true);
            return jsapiResult;
        }
        TblScaleOrder scaleOrder = TblScaleOrder.builder()
                .scaleId(scaleId)
                .amount(amount)
                .userId(ShiroUtil.getAuthUserInfo().getUserId())
                .status(0)
                .createTime(LocalDateTime.now())
                .build();
        tblScaleOrderMapper.insert(scaleOrder);
        log.info("JSAPI下单，订单id：{}", scaleOrder.getId());
        WxJsapiOrderRequest orderRequest = WxJsapiOrderRequest.builder()
                .mchid(StringUtils.trimToNull(mchId))
                .openid(ShiroUtil.getAuthUserInfo().getIdentifier())
                .description(scale.getScaleName())
                .outTradeNo(scaleOrder.getId())
                .attach(scaleId)
                .currency("CNY")
                .notifyUrl(StringUtils.trimToNull(notifyUrl))
                .total(amount)
                .build();
        String jsonResult = HttpUtils.sendPost(IamsServiceEnum.WECHAT_JSAPI_ORDER_URL.getUrl(), JSON.toJSONString(orderRequest));
        ActionResult<JsapiResult> actionResult = JSONObject.parseObject(jsonResult, new TypeReference<ActionResult<JsapiResult>>() {});
        log.info("JSAPI下单结果：{}", JSON.toJSONString(actionResult));
        if (!Objects.equals(actionResult.getCode(), ReturnStatus.SUCCESS.getCode())) {
            throw new BusinessException(actionResult.getCode(), actionResult.getMessage());
        }
        return actionResult.getData();
    }

    @Override
    public void parseOrderNotifyV3Result(String notifyData, String timeStamp, String nonce, String signature, String serial) {
        Map<String, Object> parameters = new HashMap<>();
        parameters.put("notifyData", notifyData);
        parameters.put("timeStamp", timeStamp);
        parameters.put("nonce", nonce);
        parameters.put("signature", signature);
        parameters.put("serial", serial);
        String jsonResult = HttpUtils.sendPost(IamsServiceEnum.WECHAT_PARSE_ORDER_NOTIFY_V3_RESULT_URL.getUrl(), JSON.toJSONString(parameters));
        ActionResult<WxPayOrderNotifyV3Result> notifyV3Result = JSON.parseObject(jsonResult, new TypeReference<ActionResult<WxPayOrderNotifyV3Result>>() {});
        log.info("微信小程序支付回调：{}", JSON.toJSONString(notifyV3Result));
        if (!Objects.equals(notifyV3Result.getCode(), ReturnStatus.SUCCESS.getCode())) {
            throw new BusinessException(notifyV3Result.getCode(), notifyV3Result.getMessage());
        }
        // 商户系统订单号
        WxPayOrderNotifyV3Result v3ResultData = notifyV3Result.getData();
        String outTradeNo = v3ResultData.getOutTradeNo();
        TblScaleOrder order = tblScaleOrderMapper.selectById(outTradeNo);
        if (order != null) {
            order.setPayTime(LocalDateTime.parse(v3ResultData.getSuccessTime(), DateTimeFormatter.ISO_OFFSET_DATE_TIME));
            order.setStatus(1);
            tblScaleOrderMapper.updateById(order);
            TblScalePsyRecord build = TblScalePsyRecord.builder()
                    .patId(order.getUserId())
                    .scaleId(order.getScaleId())
                    .psyType(1)
                    .createTime(order.getCreateTime())
                    .build();
            psyRecordMapper.insert(build);
        }
    }

}
